package com.weiaibenpao.demo.chislim.ui.activity.running;

import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.orhanobut.logger.Logger;
import com.weiaibenpao.demo.chislim.MyApplication;
import com.weiaibenpao.demo.chislim.R;
import com.weiaibenpao.demo.chislim.base.BaseActivity;
import com.weiaibenpao.demo.chislim.bean.FindSportType;
import com.weiaibenpao.demo.chislim.bean.SportOverInfoBean;
import com.weiaibenpao.demo.chislim.db.entities.RunningRecord;
import com.weiaibenpao.demo.chislim.db.preferences.LocationPreferences;
import com.weiaibenpao.demo.chislim.db.preferences.RunningPreferences;
import com.weiaibenpao.demo.chislim.db.preferences.UserPreferences;
import com.weiaibenpao.demo.chislim.presenter.RunPresenter;
import com.weiaibenpao.demo.chislim.service.RunningService;
import com.weiaibenpao.demo.chislim.tts.util.SpeechUtil;
import com.weiaibenpao.demo.chislim.ui.widget.RunningDataView;
import com.weiaibenpao.demo.chislim.utils.Countdown;
import com.weiaibenpao.demo.chislim.utils.RunningUtils;
import com.weiaibenpao.demo.chislim.utils.SystemUtil;
import com.weiaibenpao.demo.chislim.utils.Utils;
import com.weiaibenpao.demo.chislim.view.RunView;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.OnClick;
import io.objectbox.Box;


/**
 * Created by ZJL on 2017/12/19.
 * map生命周期，初始化地图,服务初始化，倒计时 、 Finish Confirm Dialog等通用弹框等公用逻辑封装在这
 */

public class BaseRunningActivity extends BaseActivity<RunView,RunPresenter> implements RunView, RunningService.OnDataUpdatedListener,Countdown.OnCountdownListener,RunningDataView.OnUserActionListener {
    @BindView(R.id.map_view)
    MapView mapView;
    @BindView(R.id.iv_hide_map)
    ImageView ivHideMap;
    @BindView(R.id.tv_countdown)
    TextView tvCountdown;
    @BindView(R.id.running_data_view)
    RunningDataView runningDataView;
    @BindView(R.id.view_bar)
    View viewBar;
    protected StringBuilder mLocusPhoto = new StringBuilder();       //轨迹
    protected StringBuilder mFrequencyPhoto = new StringBuilder();   //步频图
    protected StringBuilder mStridePhoto = new StringBuilder();      //步幅图
    protected StringBuilder mPaceForm = new StringBuilder();         //配速列表
    protected StringBuilder mAltitudePhoto = new StringBuilder();    //海拔图
    protected AMap aMap;
    protected Marker mMyLocationMarker;
    protected static final int THRESHOLD_DISTANCE = 100 ;//单位“米”
    protected float mCurrentDistance;
    protected boolean mIsRecoveredRunning;
    protected boolean mAlreadyAssembled;
    protected Box<RunningRecord> mRunningRecordBox;
    protected Countdown mCountdown ;
    protected RunningService mService;
    protected int userId;
    protected StringBuilder marathonType=new StringBuilder();//马拉松
    protected ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            RunningService.LocalBinder binder = (RunningService.LocalBinder) service;
            mService = binder.getService();
            mService.registerOnDataUpdatedListener(BaseRunningActivity.this);
            if (mIsRecoveredRunning) {
                doOnServiceConnectedFromRecovering();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
            Logger.e("BaseRunningActivity--onServiceDisconnected");
        }
    };
    protected List<FindSportType.MarathonListBean> marathonList;
    protected List<FindSportType.MarathonListBean> marathonListCopy = new ArrayList<>();
    protected int mTotalTime;


    @Override
    public int setLayoutResourceID() {
        return R.layout.layout_common_running;
    }

    @Override
    public void init(Bundle savedInstanceState) {
        setStatusBarIsDarkFont(true);
        Utils.setMinimumAudioVolume(0.8f);//咕咚语音音量的做法是在首次进入跑步界面设置一个比较高的音量  并且注册监听音量变化并保存到本地，以后每次进入跑步界面从本地拿出来设置作为跑步界面音量
        if(shouldInitMapByBase()) initMap(savedInstanceState);
        mRunningRecordBox = MyApplication.getInstance().getBoxStore().boxFor(RunningRecord.class);
        initService();
        runningDataView.setOnUserActionListener(this);
        int state = RunningPreferences.getInstance().getRunningState();
        if (state == RunningService.RUNNING || state == RunningService.PAUSE) {
            if (state == RunningService.PAUSE) {
                runningDataView.setState(RunningDataView.PAUSE);
            }
            setStatusBarIsDarkFont(false);
            mIsRecoveredRunning = true;
            restoreDataDisplay();//由于RunningService的回调有过滤，例如如果精度不满足，就不回调，所以这里进行一次手动恢复现场
        }else {//只有全新的跑步才有倒计时    恢复的跑步不应该有倒计时
            Typeface typeFace = Typeface.createFromAsset(getAssets(), "fonts/Reducto Condensed SSi Condensed.ttf");
            tvCountdown.setTypeface(typeFace);
            tvCountdown.setVisibility(View.VISIBLE);
            mCountdown = new Countdown(3);
            mCountdown.setOnCountdownListener(this);
            mCountdown.startCountdown();
        }
        userId = UserPreferences.getInstance().getInt(UserPreferences.USER_ID);
        mPresenter.getFindSportType(userId);
//        if(RunningPreferences.getInstance().getIsShowWhiteListNotice()){
//            showWhiteListNotice();
//        }
    }



    protected void setStatusBarIsDarkFont(boolean isDark) {
        immersionBar.
                transparentBar() //透明状态栏和导航栏，不写默认状态栏为透明色，导航栏为黑色（设置此方法，fullScreen()方法自动为true）
                .fitsSystemWindows(false)
                .statusBarDarkFont(isDark)   //状态栏字体是深色，不写默认为亮色
                .init();
    }
    /**
     * 改变状态栏的颜色
     * @param flag true 状态栏是亮色，字体是灰色
     *             false 状态栏是灰色，字体是亮色
     */
    private void initImmersionBar(boolean flag) {

    }
    protected void initService() {
        Intent serviceIntent = new Intent(this, RunningService.class);
        putExtraToServiceIntent(serviceIntent);
        startService(serviceIntent);
        bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
    }

    protected void doOnServiceConnectedFromRecovering() {}

    protected void restoreDataDisplay() {}

    protected void updateMap() {}

    protected  void uploadRunningData(){
        if (marathonList!=null && marathonType.length() == 0){ //后一个条件是为了避免重复添加
            for (int i = 0; i < marathonList.size(); i++) {
                FindSportType.MarathonListBean bean = marathonList.get(i);
                if (mCurrentDistance/1000>= bean.getGroupDistance()){
                      marathonType.append(bean.getMarathonId()).append(",").append(mTotalTime).append(";");
                }
            }
        }
    }

    protected boolean shouldInitMapByBase(){//如果需要完全自定义初始化代码那么可以重写该方法并返回false
        return true;
    }

    protected boolean shouldShowCurrentLocation(){ //如果不需要显示当前位置可以重写该方法并返回false
        return true;
    }

    protected void putExtraToServiceIntent(Intent serviceIntent) {
        serviceIntent.putExtra(RunningService.RUNNING_ACTIVITY, getClass().getCanonicalName());
        //以下两个数据没有直接在RunningService中通过UserPreference获取而是采取传递的方式是因为:如果后续把RunningService单独放到一个进程的话，
        //那么多进程情况下操作UserPreferences会有些弊端，所以这里直接避免这个问题
        serviceIntent.putExtra(RunningService.USER_WEIGHT,UserPreferences.getInstance().getFloat(UserPreferences.USER_WEIGHT));
        serviceIntent.putExtra(RunningService.USER_HEIGHT,UserPreferences.getInstance().getInt(UserPreferences.USER_HEIGHT));
    }

    protected void doFinish() {
        if (mService != null) mService.setState(RunningService.FINISH);
        finish();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mapView != null) mapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mapView != null) mapView.onPause();
    }

    /**
     * 方法必须重写
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if(mapView != null) mapView.onSaveInstanceState(outState);
    }


    @Override
    protected void onDestroy() {
        if(mCountdown != null)mCountdown.stopCountdown();
        if (mapView != null) mapView.onDestroy();
        if (mService != null) mService.unRegisterOnDataUpdatedListener();
        unbindService(mConnection);
        //上述mapView操作需要保证执行在super.onDestroy之前，因为BaseActivity的onDestroy有ButterKnife的unbind操作
        super.onDestroy();
    }


    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
            if (mService != null && mService.hasOngoingRunning()) {
                showFinishConfirm();
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    protected void showFinishConfirm() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(getString(R.string.running_notice));
        builder.setMessage(getString(R.string.finish_running_before_exit));
        builder.setNegativeButton(getString(R.string.finish), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                if(mCurrentDistance > THRESHOLD_DISTANCE){
                    showUploadDialog();
                }else {
                    showNotUploadDialog();
                }
            }
        });
        builder.setPositiveButton(getString(R.string.keep), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {

            }
        });
        builder.show();
    }

    protected void showUploadDialog(){
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(getString(R.string.running_notice));
        builder.setMessage(getString(R.string.wanna_upload_and_save));
        builder.setNegativeButton(getString(R.string.quit_upload), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                doFinish();
            }
        });
        builder.setPositiveButton(getString(R.string.upload_to_save), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {

                uploadRunningData();
            }
        });
        builder.setCancelable(false);
        builder.show();
    }

    protected void  showNotUploadDialog(){
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(getString(R.string.running_notice));
        builder.setMessage(getString(R.string.too_short_to_upload));
        builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                //do nothing
            }
        });
        builder.setPositiveButton(getString(R.string.confirm), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                doFinish();
            }
        });
        builder.setCancelable(false);
        builder.show();
    }


    protected void initMap(Bundle savedInstanceState) {
        if (mapView == null) return;
        mapView.onCreate(savedInstanceState);// 此方法必须重写
        if (aMap == null) {
            aMap = mapView.getMap();
            aMap.setOnMapLoadedListener(new AMap.OnMapLoadedListener() {
                @Override
                public void onMapLoaded() {
                    aMap.setMapType(AMap.MAP_TYPE_NORMAL);
                    if(shouldShowCurrentLocation()) setMyLocationStyleIcon();
                }
            });
        }
        UiSettings mUiSettings = aMap.getUiSettings();
        mUiSettings.setLogoPosition(2);//设置高德地图logo位置
        mUiSettings.setZoomControlsEnabled(false);
        if(shouldShowCurrentLocation()){
            aMap.setMyLocationEnabled(true);
            String latitudeStr = LocationPreferences.getInstance().getLocationLatitude();
            String longitudeStr = LocationPreferences.getInstance().getLocationLongitude();
            if (!TextUtils.isEmpty(latitudeStr) && !TextUtils.isEmpty(longitudeStr)) {
                Double latitude = Double.parseDouble(latitudeStr);
                Double longitude = Double.parseDouble(longitudeStr);
                LatLng latLng = new LatLng(latitude, longitude);
                updateCamera(latLng);
                moveLocationMarker(latLng);
            }
        }
    }

    /**
     * 自定义系统定位小蓝点
     */
    protected void setMyLocationStyleIcon() {
        MyLocationStyle myLocationStyle = new MyLocationStyle();
        ImageView iv = new ImageView(this);
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(1, 1);
//        iv.setImageResource(R.mipmap.location);
        iv.setLayoutParams(layoutParams);
        BitmapDescriptor markerIcon = BitmapDescriptorFactory.fromView(iv);
        myLocationStyle.myLocationIcon(markerIcon);          // 设置小蓝点的图标
        myLocationStyle.strokeColor(Color.argb(0, 0, 0, 0));       // 设置圆形的边框颜色
        myLocationStyle.radiusFillColor(Color.argb(0, 0, 0, 0));      // 设置圆形的填充颜色
        myLocationStyle.strokeWidth(0f);// 设置圆形的边框粗细
        myLocationStyle.anchor(0.5f, 0.9f);
        aMap.setMyLocationStyle(myLocationStyle);
    }

    /**
     * 显示地图显示中心点
     */
    protected void updateCamera(LatLng latLng) {
        if (aMap == null) return;
        aMap.moveCamera(CameraUpdateFactory.changeLatLng(latLng));
        aMap.moveCamera(CameraUpdateFactory.zoomTo(17));
    }

    protected void moveLocationMarker(final LatLng latlng) {
        if (latlng == null || aMap == null) {
            return;
        }
        aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latlng, 17f));
//        if (mMyLocationMarker != null) {
//            mMyLocationMarker.destroy();
//        }
        if (mMyLocationMarker == null) {
            final MarkerOptions markerOptions = new MarkerOptions();
            //markerOptions.snippet(dogId);
            // 设置Marker点击之后显示的标题R.drawable.local2R.mipmap.location
            //markerOptions.setFlat(false);
            markerOptions.anchor(0.5f, 0.7f);
            markerOptions.zIndex(25);
            markerOptions.zIndex(90);
            ImageView iv = new ImageView(this);
            FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(100, 100);
            iv.setImageResource(R.drawable.img_cur_location);
            iv.setLayoutParams(layoutParams);
            BitmapDescriptor markerIcon = BitmapDescriptorFactory.fromView(iv);
            markerOptions.icon(markerIcon);
            markerOptions.position(latlng);
            mMyLocationMarker = aMap.addMarker(markerOptions);
        } else {
            mMyLocationMarker.setPosition(latlng);
        }
    }


    @OnClick(R.id.iv_hide_map)
    public void onClickHideMap(View view){
        if(mapView != null){
            runningDataView.setVisibility(View.VISIBLE);
            mapView.setVisibility(View.INVISIBLE);
            ivHideMap.setVisibility(View.INVISIBLE);
            setStatusBarIsDarkFont(false);
        }
    }

    protected void showAddToWhiteListNotice(){
//        if(UserPreferences.getInstance().getIsShowWhiteListNotice()){
//            return;//避免两种提示Dialog都弹出
//        }
        if(UserPreferences.getInstance().getIsShowAddToWhiteListNotice()){
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle(getString(R.string.notice));
            String message ;
            if(SystemUtil.getSystemModel().contains(SystemUtil.MODEL_OPPO)){
                message = getString(R.string.oppo_app_killed_notice);
            }else {
                message = getString(R.string.app_killed_notice);
            }
            builder.setMessage(message);
            builder.setNegativeButton(getString(R.string.not_notify), new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    UserPreferences.getInstance().setIsShowAddToWhiteListNotice(false);
                }
            });
            builder.setPositiveButton(getString(R.string.get_it), new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                }
            });
            builder.setCancelable(true);
            builder.show();
        }
    }

    @Override
    public void onDataUpdated(Bundle data) {
        if (isDestroyed()) return;
        mCurrentDistance = data.getFloat(RunningService.DISTANCE);
        runningDataView.setData(data);
        if (marathonListCopy!=null && marathonListCopy.size()>0){
                FindSportType.MarathonListBean type = marathonListCopy.get(0);
                if (mCurrentDistance/1000 >= type.getGroupDistance()){
                    SpeechUtil.getInstance().speak(getString(R.string.congratulations_match_finished));//后台应该返回赛事名称这样更准确知道哪个赛事完成。。
                    marathonListCopy.remove(0);
                }
        }
    }

    @Override
    public void onRunningTime(int runningTime) {
        if (isDestroyed()) return;
        runningDataView.setTime(RunningUtils.getHmsTime(runningTime));
        mTotalTime=runningTime;
    }

    @Override
    public void onTick(int secondsUntilFinished) {
        if(secondsUntilFinished>0) {
            String countStr = String.valueOf(secondsUntilFinished);
            tvCountdown.setText(countStr);
            SpeechUtil.getInstance().speak(countStr);
        }else {
            tvCountdown.setVisibility(View.GONE);
            if(mService != null) mService.setState(RunningService.RUNNING);
            SpeechUtil.getInstance().speak(getString(R.string.running_started));
            setStatusBarIsDarkFont(false);
        }

    }

    @Override
    public void onClickShowMap() {
        if(mapView.getVisibility() != View.VISIBLE){
            setStatusBarIsDarkFont(true);
            ivHideMap.setVisibility(View.VISIBLE);
            mapView.setVisibility(View.VISIBLE);
            runningDataView.setVisibility(View.INVISIBLE);
            updateMap();
        }
    }

    @Override
    public void onClickPause() {
        pauseRunning();
    }

    protected void pauseRunning() {
        if(mService != null){
            mService.setState(RunningService.PAUSE);
            SpeechUtil.getInstance().speak(getString(R.string.pause_running));
        }
    }

    @Override
    public void onClickContinue() {
        continueRunning();
    }

    protected void continueRunning() {
        if(mService != null){
            mService.setState(RunningService.RUNNING);
            SpeechUtil.getInstance().speak(getString(R.string.continue_running));
        }
    }

    @Override
    public void onEndRunning() {
        if(mService != null){
            if(mCurrentDistance > THRESHOLD_DISTANCE){
                showUploadDialog();
            }else {
                showNotUploadDialog();
            }
        }
    }

    @Override
    public RunPresenter initPresenter() {
        return new RunPresenter();
    }

    @Override
    public void onUploadDataSuccess(SportOverInfoBean sportInfoBean) {

    }

    @Override
    public void onUploadDataFailed(String errMsg) {
        Toast.makeText(this,getString(R.string.save_failed)+getString(R.string.colon)+errMsg,Toast.LENGTH_LONG).show();
    }

    @Override
    public void requestFindSportSuccess(FindSportType findSportType) {
        Logger.e("requestFindSportSuccess");
     if (findSportType.getMarathonList()!=null){
         marathonList = findSportType.getMarathonList();
         Logger.e("requestFindSportSuccess MarathonList is not null");
         if(marathonList != null){
             marathonListCopy.addAll(marathonList);
          }
       }
    }

    @Override
    public void requestFindSportFailed(String errMsg) {

    }


}
